import { useContext, useEffect, useMemo, useState } from 'react'
import { Button, ReloadIcon } from '@pluralsh/design-system'
import { Flex } from 'honorable'
import { useMutation, useQuery } from '@apollo/client'
import IsEmpty from 'lodash/isEmpty'

import { useSectionError, useSectionState } from '../../context/hooks'
import {
  CloudProps,
  CloudProvider,
  CloudType,
  CreateCloudShellSectionState,
  SCMProps,
  WorkspaceProps,
} from '../../context/types'
import {
  CREATE_DEMO_PROJECT_MUTATION,
  POLL_DEMO_PROJECT_QUERY,
} from '../../../queries'
import {
  DemoProjectState,
  RootMutationType,
  RootQueryType,
  RootQueryTypeDemoProjectArgs,
  ScmProvider,
} from '../../../../../generated/graphql'
import { OnboardingContext } from '../../context/onboarding'
import { generateString } from '../../../../../utils/string'

import { DemoStatus } from './DemoStatus'

function CreateDemo({ onBack, onNext }): JSX.Element {
  const setSectionState = useSectionState()
  const setSectionError = useSectionError()
  const { setSCM, setCloud, setWorkspace } = useContext(OnboardingContext)
  const [demoCreated, setDemoCreated] = useState(false)
  const [shouldCreate, setShouldCreate] = useState(true)

  const [
    createDemoProject,
    { data: createDemoProjectResponse, error: createDemoProjectError },
  ] = useMutation<RootMutationType>(CREATE_DEMO_PROJECT_MUTATION)
  const { data: { demoProject } = {}, error: demoProjectError } = useQuery<
    Pick<RootQueryType, 'demoProject'>,
    RootQueryTypeDemoProjectArgs
  >(POLL_DEMO_PROJECT_QUERY, {
    variables: {
      id: createDemoProjectResponse?.createDemoProject?.id,
    },
    pollInterval: 2000,
    skip: !!createDemoProjectError || !createDemoProjectResponse,
  })

  const error = createDemoProjectError ?? demoProjectError
  const isProjectReady = useMemo(
    () =>
      !IsEmpty(demoProject) &&
      demoProject.state === DemoProjectState.Enabled &&
      demoProject.ready,
    [demoProject]
  )

  // On init set mode to creation and start creating demo
  useEffect(() => {
    if (shouldCreate) {
      setSectionState(CreateCloudShellSectionState.Creating)
      createDemoProject()
      setShouldCreate(false)
    }
  }, [setSectionState, createDemoProject, shouldCreate])

  // Fill onboarding props based on demo project data and prefill
  // other fields with autogenerated data
  useEffect(() => {
    if (!isProjectReady || demoCreated) return

    const suffix = generateString(5)

    setSCM({ provider: ScmProvider.Demo } as SCMProps)
    setCloud({
      type: CloudType.Demo,
      demoID: demoProject!.id,
      provider: CloudProvider.GCP,
      gcp: { applicationCredentials: demoProject!.credentials! },
    } as CloudProps)
    setWorkspace({
      project: demoProject!.projectId,
      region: 'us-east1',
      clusterName: 'demo',
      bucketPrefix: `plrlb-${suffix}`,
      subdomain: `demo-${suffix}`,
    } as WorkspaceProps)
    setDemoCreated(true)
  }, [demoCreated, demoProject, isProjectReady, setCloud, setSCM, setWorkspace])

  useEffect(() => setSectionError(!!error), [error, setSectionError])

  useEffect(() => {
    if (!demoCreated || error) return

    onNext()
    setSectionState(CreateCloudShellSectionState.Creating)
  })

  return (
    <>
      <DemoStatus
        loading={!error && demoProject?.state !== DemoProjectState.Enabled}
        error={error}
        project={demoProject ?? undefined}
      />
      {!!error && (
        <Flex
          gap="large"
          borderTop="1px solid border"
          paddingTop="large"
          paddingBottom="xsmall"
          paddingHorizontal="large"
          direction="column"
          marginTop="medium"
        >
          <Flex
            justify="space-between"
            grow={1}
            gap="medium"
          >
            <Button
              secondary
              onClick={onBack}
            >
              Back
            </Button>
            <Button
              data-phid="review-configuration"
              startIcon={<ReloadIcon />}
              alignSelf="flex-end"
              width="fit-content"
              onClick={() => setShouldCreate(true)}
            >
              Retry
            </Button>
          </Flex>
        </Flex>
      )}
    </>
  )
}

export { CreateDemo }
